/*******************************************************************************
 * Copyright (c) 2014-8-19 @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> - initial API and implementation
 ******************************************************************************/
package com.foreveross.project.projectonline.jfinal.plugin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.iff.infra.util.MapHelper;

/**
 * @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> 
 * @since 2014-8-19
 */
public class ElasticSearchClientKit {

	static ElasticSearchClientKit me = null;

	TransportClient client = null;

	public static ElasticSearchClientKit me() {
		if (me == null) {
			me = new ElasticSearchClientKit();
		}
		return me;
	}

	public TransportClient getClient() {
		if (client == null) {
			try {
				String clusterName = ResourceKit.getValue("es.cluster.name");
				String ip = ResourceKit.getValue("es.server.ip");
				Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name",
						clusterName == null ? "elasticsearch" : clusterName).put("client.transport.sniff", true)
						.build();
				String port = ResourceKit.getValue("es.server.port");
				client = new TransportClient(settings).addTransportAddress(new InetSocketTransportAddress(
						ip == null ? "localhost" : ip, new Integer(port == null ? "9300" : port)));
			} catch (Exception e) {
				try {
					if (client != null) {
						client.close();
					}
				} catch (Exception ee) {
				}
			}
		}
		return client;
	}

	public void close() {
		try {
			client.close();
		} catch (Exception e) {
		}
		client = null;
	}

	/**
	 * <pre>
	 * {
	 * 		like:{text:, fields:field1,field2}
	 * }
	 * </pre>
	 * @param conditions
	 * @return
	 * @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> 
	 * @since 2014-8-20
	 */
	public QueryBuilder like(Map<String, Object> conditions) {
		Object name = MapHelper.getByPath(conditions, "like/text");
		Object field = MapHelper.getByPath(conditions, "like/fields");
		if (name == null || field == null) {
			return null;
		}
		String[] fields = field.toString().split(",");
		return QueryBuilders.multiMatchQuery(name, fields);
	}

	/**
	 * <pre>
	 * {
	 * 		range:{field:, value:min,max}
	 * }
	 * </pre>
	 * @param conditions
	 * @return
	 * @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> 
	 * @since 2014-8-20
	 */
	public List<QueryBuilder> range(Map<String, Object> conditions) {
		List<Object> list = new ArrayList<Object>();
		List<QueryBuilder> builders = new ArrayList<QueryBuilder>();
		Object range = MapHelper.getByPath(conditions, "range");
		{
			if (range == null) {
				return builders;
			} else if (range instanceof Map) {
				list.add(range);
			} else if (range instanceof Collection) {
				list.addAll((Collection) range);
			} else if (range.getClass().isArray()) {
				list.addAll(Arrays.asList(range));
			} else {
				return builders;
			}
		}
		for (Object o : list) {
			if (!(o instanceof Map)) {
				continue;
			}
			Map<String, Object> tmp = (Map<String, Object>) o;
			Object field = MapHelper.getByPath(tmp, "field");
			Object value = MapHelper.getByPath(tmp, "value");
			if (field == null || value == null) {
				continue;
			}
			String[] values = value.toString().split(",");
			RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(field.toString());
			if (values[0].length() > 0) {
				rangeQuery.gte(Double.valueOf(values[0]));
			}
			if (values.length > 1 && values[1].length() > 0) {
				rangeQuery.lte(Double.valueOf(values[0]));
			}
			builders.add(rangeQuery);
		}
		return builders;
	}
}
